package com.xyy.saas.payment.controller;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.xyy.saas.payment.adpater.RouteManager;
import com.xyy.saas.payment.adpater.channel.setting.ChannelSettingManager;
import com.xyy.saas.payment.adpater.impl.JdCreditAdapter;
import com.xyy.saas.payment.adpater.jd.common.JDConstants;
import com.xyy.saas.payment.adpater.jdCredit.enums.JdCreditOrderStatusEnum;
import com.xyy.saas.payment.adpater.jdCredit.enums.JdCreditPayStatusEnum;
import com.xyy.saas.payment.adpater.jdCredit.req.CreditResultNotifyReq;
import com.xyy.saas.payment.adpater.jdCredit.req.FinanceResultNotifyReq;
import com.xyy.saas.payment.adpater.jdCredit.req.JDRefundNotifyReq;
import com.xyy.saas.payment.adpater.jdCredit.req.RepayNotifyReq;
import com.xyy.saas.payment.adpater.jdCredit.resp.PayOrderStatusResp;
import com.xyy.saas.payment.adpater.pingxx.domain.PayDO;
import com.xyy.saas.payment.api.impl.*;
import com.xyy.saas.payment.callback.core.dto.CallbackMsg;
import com.xyy.saas.payment.callback.core.handler.JDRefundCallbackHandler;
import com.xyy.saas.payment.callback.core.handler.JDRepayCallbackHandler;
import com.xyy.saas.payment.callback.core.handler.JdCreditContractCallBackHandler;
import com.xyy.saas.payment.callback.core.job.PinganCreditPayJob;
import com.xyy.saas.payment.callback.core.result.CallbackRunner;
import com.xyy.saas.payment.common.Constants;
import com.xyy.saas.payment.common.enums.ReconciliationType;
import com.xyy.saas.payment.common.exception.PaymentException;
import com.xyy.saas.payment.cores.enums.ResultCodeEnum;
import com.xyy.saas.payment.cores.param.*;
import com.xyy.saas.payment.cores.vo.*;
import com.xyy.saas.payment.dao.mapper.PrePayOrderMapper;
import com.xyy.saas.payment.dao.model.PayResultOrder;
import com.xyy.saas.payment.dao.model.PrePayOrder;
import com.xyy.saas.payment.dao.model.WxSettings;
import com.xyy.saas.payment.merchant.core.dto.*;
import com.xyy.saas.payment.merchant.core.service.ApplyBankcardService;
import com.xyy.saas.payment.merchant.core.service.FBank2PinganMoveService;
import com.xyy.saas.payment.merchant.core.service.SeparateOrderService2;
import com.xyy.saas.payment.payment.core.dto.ReconcileContext;
import com.xyy.saas.payment.payment.core.service.PinganCreditReconcileService;
import com.xyy.saas.payment.payment.core.service.PrePayOrderService;
import com.xyy.saas.payment.payment.core.service.ProfitSharingService;
import com.xyy.saas.payment.payment.core.service.TradeCheckService2;
import com.xyy.saas.payment.payment.core.service.reconciliation.ReconciliationExecutor;
import com.xyy.saas.payment.payment.core.service.reconciliation.ReconciliationJob;
import com.xyy.saas.payment.service.PayResultOrderService;
import com.xyy.saas.payment.util.*;
import com.xyy.saas.payment.util.mq.CallbackRechargeHandleConsumer;
import lombok.Data;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;

import javax.annotation.Resource;
import java.time.LocalDateTime;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

@Slf4j
@RestController
@RequestMapping(value = {"/api/pingan"})
public class PinganTestController {
    @Resource
    private PaymentMerchantApiImpl paymentMerchantApi;
    @Resource
    private PaymentOpenAccountApiImpl paymentOpenAccountApi;
    @Resource
    private PaymentOrderApiImpl paymentOrderApi;
    @Resource
    private PaymentSettleApiImpl paymentSettleApi;
    @Autowired
    private ChannelSettingManager channelSettingManager;
    @Resource
    private RouteManager routeManager;
    @Resource
    private SeparateOrderService2 separateOrderService2;
    @Resource
    private FBank2PinganMoveService fBank2PinganMoveService;
    @Resource
    private PaymentLoanApiImpl paymentLoanApi;
    @Resource
    private PinganCreditPayJob pinganCreditPayJob;
    @Resource
    private ReconciliationJob reconciliationJob;
    @Resource
    private ReconciliationExecutor reconciliationExecutor;
    @Resource
    private TradeCheckService2 tradeCheckService2;
    @Resource
    private CallbackRechargeHandleConsumer callbackRechargeHandleConsumer;
    @Autowired
    private CallbackUtil callbackUtil;
    @Autowired
    private ProfitSharingService profitSharingService;
    @Resource
    private ApplyBankcardService applyBankcardService;
    @Resource
    private JdCreditAdapter jdCreditAdapter;
    @Resource
    private JDRepayCallbackHandler jdRepayCallbackHandler;
    @Resource
    private JDRefundCallbackHandler jdRefundCallbackHandler;
    @Autowired
    private JdCreditContractCallBackHandler jdCreditContractCallBackHandler;
    @Autowired
    private PrePayOrderService prePayOrderService;
    @Autowired
    private PinganCreditReconcileService pinganCreditReconcileService;
    @Autowired
    private CallbackRunner callbackRunner;
    @Autowired
    private PrePayOrderMapper prePayOrderMapper;
    @Autowired
    private PayResultOrderService payResultOrderService;
    @RequestMapping(value = "/jdCreditContractCallBack", method = RequestMethod.POST)
    public ResultVO<PinganLoanPreApplyResultVo> jdCreditContractCallBack(@RequestBody CreditResultNotifyReq creditResultNotifyReq) throws PaymentException {
        try {
            log.error("jdCreditContractCallBack rep param:{}",JSONObject.toJSONString(creditResultNotifyReq));

            jdCreditContractCallBackHandler.callBack(creditResultNotifyReq);
        } catch (Exception e) {
            log.error("jdCreditContractCallBack error param:{}",JSONObject.toJSONString(creditResultNotifyReq),e);
            return ResultVO.createError(e.getMessage());
        }
        return ResultVO.createSuccess();
    }

    @RequestMapping(value = "/queryCustInfo", method = RequestMethod.POST)
    public ResultVO<FinanceAccountInfoVo> queryCustInfo(@RequestBody PinganLoanQueryApplyStatusParam param) throws PaymentException {
        try {
            log.error("queryCustInfo rep param:{}",JSONObject.toJSONString(param));
            return paymentLoanApi.queryFinanceAccountInfo(param,"");
        } catch (Exception e) {
            log.error("queryCustInfo error param:{}",JSONObject.toJSONString(param),e);
            return ResultVO.createError(e.getMessage());
        }
    }

    /**
     * 查询银行
     */
    @RequestMapping(value = "/queryJdOrerState", method = RequestMethod.GET)
    public Object queryJdOrerState(String payNo) throws PaymentException {
        PayOrderStatusResp resp = jdCreditAdapter.queryOrderStatus(payNo);
        resp.setPayStatus(JdCreditPayStatusEnum.getEnum(resp.getPayStatus()).getDesc());
        resp.setOrderStatus(JdCreditOrderStatusEnum.getEnum(resp.getOrderStatus()).getDesc());
        return resp;
    }

    /**
     * 还款计划通知
     */
    @PostMapping(value = "/jdCredit/repayNotice")
    public Object jdCreditRepayNotice(@RequestParam("payNo") String payNo) {
        RepayNotifyReq notifyReq = new RepayNotifyReq();
        notifyReq.setOrderCode(payNo);
        jdRepayCallbackHandler.doHandle(notifyReq);
        return ResultVO.createSuccess();
    }
    /**
     * 京东采购金融支付通知
     */
    @PostMapping(value = "/jdCredit/payNotice")
    public Object jdCreditPayNotice(@RequestBody FinanceResultNotifyReq jdNotifyTradeVo) {

        // 查询预支付订单
        PrePayOrder prePayOrder = prePayOrderService.getPrePayOrderByPayNo(jdNotifyTradeVo.getOrderCode());

        //支付失败直接通知业务方
        if (!JDConstants.JD_CREDIT_SUCCESS_CODE.equals(jdNotifyTradeVo.getResCode())) {
            // 异步回调业务
            String topic = ApolloUtil.getPaySuccessNotifyTopic(prePayOrder.getBusinessType(), prePayOrder.getBusinessOrderType());

            CallbackMsg callbackMsg = new CallbackMsg();
            callbackMsg.setTradeNo(prePayOrder.getPayNo());
            callbackMsg.setType(CallbackResultVo.PAY_FAIL);
            callbackMsg.setAmount(prePayOrder.getAmount());
            callbackMsg.setCallback(prePayOrder.getCallbackAddress());
            callbackMsg.setNotifyTime(DateUtil.now());
            callbackRunner.callback(topic, callbackMsg);
            return "";
        }

        // 幂等判断
        PayResultOrder payResultOrder = payResultOrderService.selectByPayNoAndChannel(jdNotifyTradeVo.getOrderCode(), "jd_credit");

        if(payResultOrder != null) {
            log.error("jd credit pay callback repeat payNo:{}", jdNotifyTradeVo.getOrderCode());
//            throw new PaymentException(ResultCodeEnum.REQUEST_PROCESSED);
            return "";
        }

        JSONObject extra = (StringUtils.isBlank(prePayOrder.getExtra()) ? new JSONObject() : JSONObject.parseObject(prePayOrder.getExtra()));
        // 基本参数
        PayDO payDO = new PayDO();
        //todo 商户号没有
//        payDO.setMchId(params.getString("merchantNo"));
        payDO.setOrderNo(jdNotifyTradeVo.getOrderCode());
//        payDO.setChannelChargeNo(jdNotifyTradeVo.getLoanNo());
        payDO.setAmount(AmountCastUtil.castYuan2Fen(jdNotifyTradeVo.getPayAmount()));
        payDO.setChannel(Constants.CHANNEL_JD_CREDIT);
        payDO.setPayMode(extra.getString("payMode"));
        payDO.setResultCode(transTradeStatus(jdNotifyTradeVo.getApplyStatus()));
        //借据单号//TODO 验证这个字段
        payDO.setChannelTransactionNo(jdNotifyTradeVo.getLoanNo());
        payDO.setTimePaid(StringUtils.isBlank(jdNotifyTradeVo.getPayDate()) ? null : DateUtil.parase(jdNotifyTradeVo.getPayDate(), DateUtil.YYYYMMDDHHMMSS));
        //todo 失败码后面干啥用了
        //payDO.setFailureCode(jdNotifyTradeVo.getResultCode() + "|" + jdNotifyTradeVo.getResultDesc());
        payDO.setFailureMsg(jdNotifyTradeVo.getResDesc());
        // 其他参数
        payDO.setNotifyTime(DateUtil.now());
        payDO.setCount(0);
        payDO.setExtra(prePayOrder.getExtra());
        payDO.setBusinessType(prePayOrder.getBusinessType());
        payDO.setBusinessOrderType(prePayOrder.getBusinessOrderType());
        payDO.setReceiverId(prePayOrder.getReceiverId());
        payDO.setCallbackAddress(prePayOrder.getCallbackAddress());
        payDO.setPayer(prePayOrder.getPayer());

        payDO.setNotifyTime(DateUtil.now());

        // 检验订单金额
        if(!payDO.getAmount().equals(prePayOrder.getAmount())) {
            // 回调进来的金额和发起订单金额不等
            log.error("JdCreditPayResultHandler#callBackHandler callback amount error  payDo:{} pay:{}", JSON.toJSONString(payDO), JSON.toJSONString(prePayOrder));
            return ResultVO.createError(ResultCodeEnum.PARAM_ERROR);
        }


        payDO.setBusinessType(prePayOrder.getBusinessType());
        payDO.setBusinessOrderType(prePayOrder.getBusinessOrderType());
        payDO.setReceiverId(prePayOrder.getReceiverId());
        payDO.setCallbackAddress(prePayOrder.getCallbackAddress());
        payDO.setPayer(prePayOrder.getPayer());
        payDO.setCount(0);
        callbackRunner.callbackPingXX(payDO);

        return ResultVO.createSuccess();
    }

    public static String transTradeStatus(String tradeStatus) {
        if (tradeStatus.equals(JdCreditPayStatusEnum.PAID.getCode())) {
            return "SUCCESS";
        } else if (tradeStatus.equals(JdCreditPayStatusEnum.FAIL.getCode())) {
            return "FAIL";
        }
        throw new RuntimeException("交易状态错误");
    }
    /**
     * 京东采购金融退款通知
     */
    @PostMapping(value = "/jdCredit/refundNotice")
    public Object jdCreditRefundNotice(@RequestBody JDRefundNotifyReq notifyReq) {
        jdRefundCallbackHandler.doHandle(notifyReq);
        return ResultVO.createSuccess();
    }

    /**
     * 查询银行
     */
    @RequestMapping(value = "/bankQuery", method = RequestMethod.POST)
    public Object bankQuery(@RequestBody BankQueryParam param) {
        return paymentMerchantApi.bankQueryV2(param);
    }

    /**
     * 查询支行
     */
    @RequestMapping(value = "/subBankQuery", method = RequestMethod.POST)
    public Object subBankQuery(@RequestBody SubBankQueryParam param) {
        return paymentMerchantApi.subBankQueryV2(param);
    }

    /**
     * 企业开户
     */
    @RequestMapping(value = "/createMerchant", method = RequestMethod.POST)
    public Object createMerchant(@RequestBody MerchantAccountCreateVo param) {
        return paymentMerchantApi.merchantCertifyAccountCreate(param, StringUtils.EMPTY);
    }

    /**
     * 企业开户 + 绑卡
     */
    @RequestMapping(value = "/createMerchantAndBind", method = RequestMethod.POST)
    public Object createMerchant(@RequestBody MerchantAccountVO merchantAccountVO) {
        return paymentOpenAccountApi.create(merchantAccountVO, StringUtils.EMPTY);
    }

    /**
     * 打款认证
     */
    @RequestMapping(value = "/paymentAuth", method = RequestMethod.POST)
    public Object paymentAuth(@RequestBody PaymentAuthParam param) {
        return paymentOpenAccountApi.paymentAuth(param);
    }

    /**
     * 查询账户信息
     */
    @RequestMapping(value = "/queryAccountInfo", method = RequestMethod.POST)
    public Object queryAccountInfo(@RequestBody AccountInfoParam param) {
        return paymentOpenAccountApi.queryAccountInfo(param);
    }

    /**
     * 企业换绑
     */
    @RequestMapping(value = "/merchantSettleCardReBind", method = RequestMethod.POST)
    public Object merchantSettleCardReBind(@RequestBody MerchantSettleCardBindVo param) {
        return paymentMerchantApi.merchantSettleCardReBind(param, StringUtils.EMPTY);
    }

    /**
     * 结算
     */
    @RequestMapping(value = "/profitSharing", method = RequestMethod.POST)
    public Object profitSharing(@RequestBody ProfitSharingParam param) {
        return paymentSettleApi.profitSharing(param, StringUtils.EMPTY);
    }

    /**
     * 查询账户余额
     */
    @RequestMapping(value = "/queryAccount", method = RequestMethod.POST)
    public Object queryAccount(@RequestBody QueryAccountVo queryAccountVo) {
        return paymentMerchantApi.queryAccount(queryAccountVo, StringUtils.EMPTY);
    }

    /**
     * 查询账户余额
     */
    @RequestMapping(value = "/queryAccountByNo", method = RequestMethod.POST)
    public Object queryAccountByNo(@RequestParam(value = "accountNo") String accountNo, @RequestParam(value = "balanceAccountType") String balanceAccountType) {
        return paymentMerchantApi.queryAccountByAccountNo(accountNo, balanceAccountType);
    }

    /**
     * 提现
     */
    @RequestMapping(value = "/withdraw", method = RequestMethod.POST)
    public Object withdraw(@RequestBody OrderWithdrawVo orderWithdrawVo) {
        return paymentOrderApi.withdraw(orderWithdrawVo, StringUtils.EMPTY);
    }

    /**
     * 查询支付状态
     */
    @RequestMapping(value = "/queryTransactionInfo", method = RequestMethod.POST)
    public Object queryTransactionInfo(@RequestBody TransactionParam param) {
        return paymentOrderApi.queryTransactionInfo(param, StringUtils.EMPTY);
    }

    @RequestMapping(value = "/queryTransactionStatus", method = RequestMethod.POST)
    public Object queryTransactionStatus(@RequestBody QueryTransactionStatusDto queryTransactionStatusDto) throws PaymentException {
        return routeManager.queryTransactionStatus(queryTransactionStatusDto, StringUtils.EMPTY);
    }

    @RequestMapping(value = "/orderSupply", method = RequestMethod.POST)
    public Object orderSupply(@RequestBody OrderSupplyDto param) throws PaymentException {
        return routeManager.orderSupply(param);
    }

    @RequestMapping(value = "/queryThirdUserId", method = RequestMethod.POST)
    public Object queryThirdUserId(@RequestBody QueryThirdUserIdDto param) throws PaymentException {
        return routeManager.queryThirdUserId(param);
    }

    /**
     * 冻结余额查询
     */
    @RequestMapping(value = "/queryOrderAmountInfo", method = RequestMethod.POST)
    public OrderAmountInfoVo queryOrderAmountInfo(@RequestBody OrderAmountInfoDto param) throws PaymentException {
        return routeManager.queryOrderAmountInfo(param);
    }

    /**
     * 检验微信配置
     */
    @RequestMapping(value = "/checkWxConfig", method = RequestMethod.POST)
    public Object checkWxConfig(String receiveId, String businessOrderType, String payMode) throws Exception {
        WxSettings wxSettings = channelSettingManager.getWXSettings(receiveId, businessOrderType, payMode);
        log.info("wxSettings={}", JSONUtils.toJSON(wxSettings));
        WxUtil.initKeyStoreByPem(wxSettings.getApiCertificate(), wxSettings.getPrivateKey(), wxSettings.getMerchantId());
        return "SUCCESS";
    }

    /**
     * 会员间交易
     */
    @RequestMapping(value = "/accountTransfer", method = RequestMethod.POST)
    public Object accountTransfer(@RequestBody AccountTransferDto param) throws PaymentException {
        separateOrderService2.accountTransfer(param);
        return "SUCCESS";
    }

    /**
     * 会员间交易撤销
     */
    @RequestMapping(value = "/accountTransferRefund", method = RequestMethod.POST)
    public Object accountTransferRefund(@RequestBody AccountTransferRefundDto param) throws PaymentException {
        separateOrderService2.accountTransferRefund(param);
        return "SUCCESS";
    }

    /**
     * 分账
     */
    @RequestMapping(value = "/settle", method = RequestMethod.POST)
    public Object settle(@RequestBody SettleOrderDto param) throws PaymentException {
        separateOrderService2.settle(param);
        return "SUCCESS";
    }

    /**
     * 分账撤销
     */
    @RequestMapping(value = "/settleCancel", method = RequestMethod.POST)
    public Object settleCancel(@RequestBody SettleCancelDto param) throws PaymentException {
        separateOrderService2.settleCancel(param);
        return "SUCCESS";
    }

    /**
     * 登记挂账
     */
    @RequestMapping(value = "/registerOrder", method = RequestMethod.POST)
    public Object registerOrder(@RequestBody RegisterOrderDto param) throws PaymentException {
        separateOrderService2.registerOrder(param);
        return "SUCCESS";
    }

    @RequestMapping(value = "/queryChannelClear", method = RequestMethod.POST)
    public QueryChannelClearVo queryChannelClear(@RequestBody QueryChannelClearDto param) throws PaymentException {
        return routeManager.queryChannelClear(param);
    }

    /**
     * 查询对账文件信息
     */
    @RequestMapping(value = "/queryReconciliationFile", method = RequestMethod.POST)
    public QueryReconciliationFileVo queryReconciliationFile(@RequestBody QueryReconciliationFileDto param) throws PaymentException {
        return routeManager.downReconciliationFile(param);
    }

    @RequestMapping(value = "/move", method = RequestMethod.POST)
    public Object move(String businessIdType, String fromBusinessId, String toBusinessId) throws PaymentException {
        fBank2PinganMoveService.move(businessIdType, fromBusinessId, toBusinessId);
        return "SUCCESS";
    }

    @RequestMapping(value = "/payFiancePreApply", method = RequestMethod.POST)
    public ResultVO<PinganLoanPreApplyResultVo> payFiancePreApply(@RequestBody PinganLoanPreApplyParam param) throws PaymentException {
        return paymentLoanApi.payFiancePreApply(param,"");
    }

    @RequestMapping(value = "/payFianceApplyStatus", method = RequestMethod.POST)
    public ResultVO<PinganLoanQueryApplyStatusVo> payFianceApplyStatus(@RequestBody PinganLoanQueryApplyStatusParam param) throws PaymentException {
        return paymentLoanApi.payFianceApplyStatus(param,"");
    }

    @RequestMapping(value = "/payFianceSendCustomerData", method = RequestMethod.POST)
    public ResultVO<String> payFianceSendCustomerData(@RequestBody PinganLoanDatasToSendDto param) throws PaymentException {
        return paymentLoanApi.payFianceSendCustomerData(param,"");
    }

    @RequestMapping(value = "/pinganLoanTestData", method = RequestMethod.POST)
    public String pinganLoanTestData(@RequestBody Map<String,Object> paramsMap) {
        String requestURL = "https://bfiles-stg.pingan.com.cn/lum/stp/guest/kybly/all/burieddata";
        JSONObject reqParams = new JSONObject(paramsMap);
        log.info("pinganLoanTestData, reqParams: {}", reqParams.toJSONString());
        String responseBody = null;
        try {
            responseBody = HttpClientUtil.xyyHttpPostRequest(requestURL, reqParams.toJSONString(), "application/json;charset=utf-8");
        } catch (Exception e) {
            log.error("pinganLoanTestData, error", e);
            return e.toString();
        }
        log.info("pinganLoanTestData, response: {}", responseBody);
        return responseBody;
    }

    @RequestMapping(value = "/pinganCreditPayJob", method = RequestMethod.POST)
    @ResponseBody
    public String pinganCreditPayJob() throws PaymentException {
        pinganCreditPayJob.execute(null);
        return "success";
    }

    @PostMapping("/tradeCheckService2")
    public String tradeDetailStrategy(@RequestBody ReconciliationExecutorParam param) {
        Integer flag = param.getFlag();
        if (flag == null) {
            return "error";
        }

        ReconcileContext context = new ReconcileContext()
                .setBeginTime(DateUtil.toLocalDateTime(param.getBeginTime()))
                .setEndTime(DateUtil.toLocalDateTime(param.getEndTime()));

        if (flag == 1) {
            tradeCheckService2.reconcileTradeDetailsWithFbank2SeparateOrder(context);
        } else if (flag == 2) {
            tradeCheckService2.reconcileTradeDetailsWithFbank2PayResultOrder(context);
        } else if (flag == 3) {
            tradeCheckService2.reconcileTradeDetailsWithFbank2RefundOrder(context);
        }
        return "done";
    }

    @PostMapping(value = "/reconciliationJob")
    public String ReconciliationJob() {
        reconciliationJob.execute(null);
        return "success";
    }

    @PostMapping("/reconciliationExecutor/execute")
    public String reconciliationExecutor(@RequestBody ReconciliationExecutorParam param) {
        ReconcileContext context = new ReconcileContext()
                .setBeginTime(DateUtil.toLocalDateTime(param.getBeginTime()))
                .setEndTime(DateUtil.toLocalDateTime(param.getEndTime()))
                .setBusinessUserIds(param.getBusinessUserIds());
        new Thread(() -> reconciliationExecutor.execute(param.getTypes(), context),
                String.join("-", "reconciliationExecutor", LocalDateTime.now().format(DateUtil.PATTERN_DATE)))
                .start();
        return "done";
    }

    @Data
    public static class ReconciliationExecutorParam {
        private Integer flag;
        private List<ReconciliationType> types;
        private String beginTime;
        private String endTime;
        private List<String> businessUserIds;
    }

    @RequestMapping(value = "/queryTradeStatus", method = RequestMethod.POST)
    public Object queryTradeStatus(@RequestBody QueryTradeStatusDto param) throws PaymentException {
        log.info("PinganTestController#queryTradeStatus param={}", JSONUtils.toJSON(param));
        return routeManager.queryTradeStatus(param);
    }

    @RequestMapping(value = "/commonRechargeRefund", method = RequestMethod.POST)
    public Object commonRechargeRefund() throws PaymentException {
        CommonRechargeRefundDto commonRechargeRefundDto = CommonRechargeRefundDto.builder().
                businessIdType("ec_self_support_mini_XS530000").
                accountId("119c").
                channel("0002").
                origChannelTradeNo("2022122322001408141421257656").
                tradeAmount(1).
                build();
        commonRechargeRefundDto.buildDetail("1606118343910096992", "4294000000005586", 1);

        return routeManager.commonRechargeRefund(commonRechargeRefundDto);
    }

    /**
     * 处理充值
     */
    @RequestMapping(value = "/handlePay", method = RequestMethod.POST)
    public Object handlePay(@RequestBody RechargeHandleDto rechargeHandleDto) throws PaymentException {
        callbackRechargeHandleConsumer.handlePay(rechargeHandleDto);
        return "done";
    }

    /**
     * 处理充值撤销
     */
    @RequestMapping(value = "/handleRefund", method = RequestMethod.POST)
    public Object handleRefund(@RequestBody RechargeHandleDto rechargeHandleDto) throws PaymentException {
        callbackRechargeHandleConsumer.handleRefund(rechargeHandleDto);
        return "done";
    }

    /**
     * 重新回调EC
     */
    @RequestMapping(value = "/callback_ec_refund", method = RequestMethod.POST)
    public Object callBackEcRefunc(@RequestBody ResultVO resultVO) {
        callbackUtil.sendRPCMsg("ec_refund", resultVO, 0);
        return "done";
    }

    /**
     * 更新商户信息
     */
    @RequestMapping(value = "/update_account", method = RequestMethod.POST)
    public Object updateAccount(@RequestBody AccountUpdateVo accountUpdateVo) {
        try {
            paymentOpenAccountApi.updateAccount(accountUpdateVo);
        } catch (Exception e) {
            log.error("updateAccount error.", e);
            return "error";
        }
        return "done";
    }

    /**
     * 重试所有待处理分润
     */
    @PostMapping(value = "/retry_all_profit")
    public Object retryAllProfit(Long minId,Integer status) {
        profitSharingService.retryAllProfit(minId,status);
        return "done";
    }

    /**
     * 获取打款认证状态
     */
    @GetMapping(value = "/sync_apply_bank")
    public Object syncApplyBank() {
        applyBankcardService.syncApplyStatus();
        return "done";
    }

    @GetMapping("/verifyCreditPaySettle")
    public Object verifyCreditPaySettle() {
        pinganCreditReconcileService.verifyCreditPaySettle();
        return "done";
    }

    @GetMapping("/verifyCreditPayRefund")
    public Object verifyCreditPayRefund() {
        pinganCreditReconcileService.verifyCreditPayRefund();
        return "done";
    }

    @PostMapping("/resendPaySuccessMsg")
    public String resendPaySuccessMsg(@RequestBody List<String> payNos) {
        if (payNos == null || payNos.isEmpty()) {
            return Constants.SUCCESS;
        }
        // 预支付单
        List<PrePayOrder> prePayOrders = prePayOrderMapper.getPrePayOrderByPayNos(payNos);
        Map<String, PayResultOrder> payResultOrderMap = payResultOrderService.selectListByPayNos(payNos).stream().collect(Collectors.toMap(p -> p.getPayNo(), p -> p));

        for (PrePayOrder prePayOrder : prePayOrders) {
            PayResultOrder payResultOrder = payResultOrderMap.get(prePayOrder.getPayNo());
            if (payResultOrder == null) {
                log.error("resendPaySuccessMsg#payResultOrder not exist:{}", prePayOrder.getPayNo());
                continue;
            }

            String channel = Constants.convertPayChannelToChannel(payResultOrder.getPayChannel(), payResultOrder.getBusinessType());

            Long unixTime = payResultOrder.getCtime().getTime() / 1000;
            String topic = ApolloUtil.getPaySuccessNotifyTopic(payResultOrder.getBusinessType(), payResultOrder.getBusinessOrderType());
            CallbackMsg msg = CallbackMsg.build(payResultOrder.getPayNo(), CallbackResultVo.TYPE_CHARGE_SUCCESS,
                    payResultOrder.getAmount(), payResultOrder.getFee(), unixTime, prePayOrder.getCallbackAddress(), channel, DateUtil.now(), payResultOrder.getMerchantId());
            msg.setBusinessOrderNo(prePayOrder.getBusinessOrderNo());
            msg.setChannelOrderNo(payResultOrder.getChannelTransactionNo());
            log.info("resendPaySuccessMsg#topic {} msg {}", topic, JSON.toJSONString(msg));
            callbackRunner.callback(topic, msg);
        }

        return Constants.SUCCESS;
    }

}
